<?php

namespace App\ServicesNew\Impl;

use App\BO\CartItem\CreateCartItemInfo;
use App\BO\PropertyAccessAndSetBO;
use App\BO\User\UserCouponBO;
use App\Entities\CartItemEntity;
use App\Entities\CartItemModel;
use App\Entities\CouponCodeEntity;
use App\ServicesNew\CartService;
use App\ServicesNew\CouponService;
use App\ServicesNew\ProductSkuService;
use App\Utils\Assert;
use Illuminate\Support\Facades\DB;

class CartServiceImpl implements CartService
{
    /**
     * @var ProductSkuService
     */
    private $productSkuService;

    /**
     * @var CouponService
     */
    private $couponService;

    public function __construct(CouponService $couponService, ProductSkuService $productSkuService)
    {
        $this->productSkuService = $productSkuService;
        $this->couponService = $couponService;
    }

    /**
     * @inheritDoc
     */
    public function getCartItemEntityByUserId(int $userId)
    {
        $model = CartItemModel::where('user_id', $userId)
            ->orderBy('id', 'desc')
            ->first();
        if (is_null($model)) {
            return null;
        }
        return new CartItemEntity($model);
    }

    /**
     * @param CartItemEntity $cartItemEntity
     * @return CouponCodeEntity[]|array
     * @throws \Exception
     */
    private function getCoupon(CartItemEntity $cartItemEntity)
    {
        $productSkuEntity = $this->productSkuService->getProductSkuEntityById($cartItemEntity->getProductSkuId());
        Assert::notNull($productSkuEntity);
        if (!$productSkuEntity->getCouponUseable()) {
            return [];
        }

        $couponCodeEntities = $this->couponService->getUseAbleCouponCodeListByUserId($cartItemEntity->getUserId());
        if (empty($couponCodeEntities)) {
            return [];
        }
        return $couponCodeEntities;
    }

    /**
     * @inheritDoc
     */
    public function getUseAbleCouponByCartItemEntity(CartItemEntity $cartItemEntity)
    {
        $couponCodeEntities = $this->getCoupon($cartItemEntity);
        return UserCouponBO::filterByCartItemEntity($cartItemEntity, $couponCodeEntities);
    }

    /**
     * @inheritDoc
     */
    public function useAbleGroupByCouponByCartItemEntity(CartItemEntity $cartItemEntity)
    {
        $couponCodeEntities = $this->getCoupon($cartItemEntity);
        return UserCouponBO::groupByUseAble($cartItemEntity, $couponCodeEntities);
    }

    /**
     * @inheritDoc
     */
    public function useAbleCouponCheckByCartItemEntity(CartItemEntity $cartItemEntity, CouponCodeEntity $couponCodeEntity)
    {
        $ret = UserCouponBO::filterByCartItemEntity($cartItemEntity, [$couponCodeEntity]);
        return empty($ret) ? false : true;
    }

    /**
     * @inheritDoc
     */
    public function clearUserCartItem(int $userId)
    {
        CartItemModel::where('user_id', $userId)->delete();
    }

    /**
     * @inheritDoc
     */
    public function createCartItem(CreateCartItemInfo $createCartItemInfo)
    {
        DB::beginTransaction();

        $this->clearUserCartItem($createCartItemInfo->getUserId());

        $cartItemEntity = CartItemEntity::getNewInstance();
        PropertyAccessAndSetBO::sync($createCartItemInfo, $cartItemEntity, PropertyAccessAndSetBO::getKeys($createCartItemInfo));
        $cartItemEntity->setSquareMetre($createCartItemInfo->getNum());
        $cartItemEntity->save();

        DB::commit(); ;
    }
}
